﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.SharePoint;
using DVK.SP2007.UniversalClient;
using DVK.SP2007.Constants;
using DVK.SP2007.Resources;

namespace DVK.SP2007
{
    /// <summary>
    /// Static MessageArchiving class. 
    /// Encapsulates all DVK message archiving capabilities.
    /// </summary>
    public static class MessageArchiver
    {
        /// <summary>
        /// Adds new or gets existing monthly folder in the message archive list.
        /// </summary>
        /// <param name="web">The web.</param>
        /// <returns></returns>
        public static SPFolder AddOrGetMonthlyFolder(SPWeb web)
        {
            SPList archiveList = web.GetListFromUrl(Constants.Urls.ListDvkMessageArchive);

            //Pattern: 122008 (MonthYear)
            string folderName = DateTime.Now.ToString("MMyyyy");
            //Check if the folder exists and return if it does
            foreach (SPFolder subFolder in archiveList.RootFolder.SubFolders)
            {
                if (subFolder.Name == folderName)
                {
                    return subFolder;
                }
            }
            //If it doesnt, create a new one
            //string targetPath = archiveList.RootFolder.ServerRelativeUrl + "/" + folderName;
            SPFolder newSubFolder = archiveList.RootFolder.SubFolders.Add(folderName);
            return newSubFolder;
        }

        /// <summary>
        /// Archives the item.
        /// Copies existing item to DVK archive list and deletes from the old list (DvkInbox or DvkOutbox).
        /// </summary>
        /// <param name="targetFolder">The target folder.</param>
        /// <param name="itemToArchive">The item to archive.</param>
        /// <exception cref="DVK.SP2007.DvkException">Throws DvkException when fails.</exception>
        public static void ArchiveItem(SPWeb web, SPFolder targetFolder, SPListItem itemToArchive)
        {
            string extensionPart = itemToArchive.Name.Substring(itemToArchive.Name.LastIndexOf('.'));
            string namePart = itemToArchive.Name.Remove(itemToArchive.Name.LastIndexOf('.'));
            string targetUrl = string.Format(
                                    "{0}{1}/{2}_{3}{4}", 
                                    web.Url,
                                    targetFolder.ServerRelativeUrl,
                                    namePart,
                                    itemToArchive.ID,
                                    extensionPart);
            try
            {
                itemToArchive.CopyTo(targetUrl);
                itemToArchive.Delete();
            }
            catch (Exception exc)
            {
                string text = string.Format("Failed to archive item (targetUrl={0}; itemToArchive={1}; itemId={2})\n", targetUrl, itemToArchive.Name, itemToArchive.ID);
                throw new DvkException(text, exc);
            }
        }

        /// <summary>
        /// Checks wether there already is a item in the outbox list with the same filename.
        /// If yes, then it tries to move it to archive. Only items with "Sent" status, can be moved to archive.
        /// </summary>
        /// <param name="web">The web.</param>
        /// <param name="targetUrl">The target URL.</param>
        public static void CheckOutboxAndMoveToHistory(SPWeb web, string targetUrl)
        {
            SPListItem item = null;
            try
            {
                item = web.GetListItem(targetUrl);
            }
            catch 
            {
                //Item does not exist
                return;
            }

            if (item == null)
                return;

            var sendingStatus = (DvkSendingStatus)item[Fields.SendingStatus.Name];

            if (sendingStatus == DvkSendingStatus.Sent)
            {
                SPFolder targetFolder = MessageArchiver.AddOrGetMonthlyFolder(web);
                MessageArchiver.ArchiveItem(web, targetFolder, item);
            }
            else if (sendingStatus == DvkSendingStatus.Sending || sendingStatus == DvkSendingStatus.Waiting)
            {
                //Only used from SendToDVK, so ASP.NET can be used.
                throw new DvkException(DvkWeb.SendToDVK_ExceptionItemWithTheFilenameExists);
            }
        }

        /// <summary>
        /// Checks wether an item already exists in the inbox list.
        /// <remarks>
        /// If item exists in the inbox list, it checks wether the item has been moved to a document library.
        /// If it has, then it will move the listitem to archive list and allow proceeding with reciving the document.
        /// If the item is in the list and hasnt been moved, then exception is thrown and reciving is cancelled for this time.
        /// The problem is, that you cannot have multiple items with the same path in the same folder at the same time.
        /// </remarks>
        /// </summary>
        /// <param name="web">The web.</param>
        /// <param name="targetUrl">The target URL.</param>
        public static void CheckInboxAndMoveToHistory(SPWeb web, string targetUrl)
        {
            SPListItem existingItem = null;
            try
            {
                existingItem = web.GetListItem(targetUrl);
            }
            catch
            {
                //Item does not exist
                return;
            }

            if (existingItem == null)
                return;

            var documentLibraryItemId = existingItem[Fields.DocumentLibraryItemId.Name] as int?;

            if (documentLibraryItemId.HasValue && documentLibraryItemId.Value > 0)
            {
                SPFolder targetFolder = MessageArchiver.AddOrGetMonthlyFolder(web);
                MessageArchiver.ArchiveItem(web, targetFolder, existingItem);
            }
            else
            {
                throw new DvkException(
                    string.Format(
                    "{0}: Inbox list contains document with the same filename and which has not yet been moved to document library. Cannot accept a new file with the same name. (targetUrl: {1}, Name: {2})",
                    web.Url,
                    targetUrl,
                    existingItem.Name
                    ));
            }
        }
    }
}
